home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 10
/
FM Towns Free Software Collection 10.iso
/
ms_dos
/
lib
/
happyai3
/
hpint3.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1994-12-10
|
38KB
|
893 lines
(*********************************************************************
* *** HAPPy P-code Interpreter for HAPPy Version 0.3 *** *
* *
* HAPPyのサンプルプログラム *
* (作者 浅野比富美 Public Domain Software) *
*********************************************************************)
(*
HPASM3.PASをコンパイルしてできるアセンブラで作成したP-codeオブジェクトを
解釈実行します。
const,type,var の各部にある * 印がついたものは、アセンブラ、インタプリタ
共通の定義項目です。
*)
program HAPPyPcodeInterpreter(pCode,pConst,input,output) ;
label 9999 ; { プログラム出口 }
const
{*} SetLow = 0 ; { HAPPy 集合要素順序数 下限値 }
{*} SetHigh = 31 ; { HAPPy 集合要素順序数 上限値 }
{*} MaxCode = 1000 ; { コード部上限 }
{*} MaxData = 3000 ; { データ部上限 }
NilValue = -1 ; { ポインタ nil値 }
(***** データ種別番号 *****)
{*} Inte = 1 ; { 整数データ }
{*} Reals = 2 ; { 実数データ }
{*} Chars = 3 ; { 文字データ }
{*} Bool = 4 ; { 論理データ }
{*} Sets = 5 ; { 集合データ }
{*} datAd = 6 ; { データ部アドレス }
{*} codAd = 7 ; { コード部アドレス }
{*} Multi = 8 ; { 列データ }
{*} Nils = 9 ; { nilデータ }
{*} Proc = 10 ; { 手続き }
type
(*** P-code命令の定義 ***)
{*} opType = { アルファベット順に並べること }
( iABI, { absolute integers }
iABR, { absolute reals }
iADI, { add integers }
iADR, { add reals }
iAND, { and operator }
iATN, { arctan standard function }
iBAS, { load base mark address }
iCHK, { check value between bounds }
iCHR, { chr standard function }
iCKA, { check address }
iCKS, { check set (P-codeソース上に現れない) }
iCOS, { cos standard function }
iCUI, { call user procedure indirect }
iCUP, { call user procedure }
iDEC, { decrement }
iDIF, { difference set }
iDIS, { dispose standard procedure }
iDVI, { divide integers }
iDVR, { divide reals }
iEJP, { extra block jump }
iENT, { enter procedure or function }
iEOF, { eof standard function }
iEOL, { eoln standard function }
iEQU, { equal operator }
iEXP, { exp standard function }
iFJP, { jump on false }
iFLO, { float integer to real on sp-1 }
iFLT, { float integer to real }
iGEQ, { grater than equal operator }
iGET, { get from not text } { not support }
iGRT, { grater than operator }
iINC, { increment }
iIND, { indexed fetch }
iINN, { in operator }
iINT, { intersection set }
iIOR, { or operator }
iIXA, { indeced address }
iLAO, { load base-level address }
iLAP, { load address of procedure }
iLCA, { load address of constant }
iLDA, { load level p address }
iLDC, { load constant }
iLDO, { load contents of base-level address }
iLEQ, { less than equal operator }
iLES, { less than operator }
iLOD, { load contents of address at level p }
iLOG, { ln standard function }
iMMS, { make multiple set }
iMOD, { modulo operator }
iMOV, { move }
iMPI, { mulutiple integers }
iMPR, { mulutiple reals }
iMSI, { mark stack indirect }
iMST, { mark stack }
iNEQ, { not equal operator }
iNEW, { new standard procedure }
iNGI, { negative integers }
iNGR, { negative reals }
iNOT, { not operator }
iNXT, { next to }
iNXD, { next downto }
iODD, { odd standard function }
iORD, { ord standard function }
iPGE, { page standard procedure }
iPUT, { put from not text } { not support }
iRDC, { read char }
iRDI, { read integer }
iRDR, { read real }
iRET, { return from procedure or function }
iRLN, { readln standard procedure }
iROU, { round }
iRST, { reset for not text } { not support }
iRWT, { rewrite for not text } { not support }
iSBI, { subtract integers }
iSBR, { subtract reals }
iSGS, { create singleton set }
iSIN, { sin standard function }
iSQI, { square integers }
iSQR, { square reals }
iSQT, { sqrt standard function }
iSRO, { store at base-level address }
iSTO, { store indirect }
iSTP, { stop }
iSTR, { store contents at address at level p }
iTGT, { get from text }
iTPT, { put from text }
iTRA, { trace of execution }
iTRC, { trunc standard function }
iTRS, { reset for text file }
iTRW, { rewrite for text file }
iUJC, { check uncondition jump }
iUJP, { uncondition jump }
iUNI, { union set }
iWLN, { writeln standard procedure }
iWRB, { write boolean }
iWRC, { write char }
iWRF, { write real fix }
iWRI, { write integer }
iWRR, { write real }
iWRS, { write string }
iXJP, { indexed jump }
iZZZ { 終わり }
) ;
{*} codeRange = 0..MaxCode ; { コード部の添字範囲 }
{*} dataRange = 0..MaxData ; { データ部の添字範囲 }
{*} dataRange1 = -1..MaxData ; { データ部の添字範囲(-1を含む)}
{*} setType = set of SetLow..SetHigh;{ 集合 (HAPPy要素順序数制限内)}
{*} pType = 0..255 ; { p オペランドの型 }
{*} codeType = record { コード部の中身 }
op : opType ; { オペレーション }
p : pType ; { p オペランド }
q : integer { q オペランド }
end ;
{*} dataKind = Inte..CodAd ; { dataTypeに用いるもの}
{*} dataType = record case dataKind of
Inte : (vi : integer) ; { 整数型・列挙型データ }
Reals : (vr : real) ; { 実数型データ }
Chars : (vc : char) ; { 文字型データ }
Bool : (vb : Boolean) ; { 論理型データ }
Sets : (vs : setType) ; { 集合型データ }
DatAd : (va : dataRange1) ; { データ部アドレス }
CodAd : (vp : codeRange) { コード部アドレス }
end ;
var
{*} pcode : file of codeType ; { P-code コードファイル }
{*} pConst : file of dataType ; { P-code 定数ファイル }
(*** P-code仮想計算機記憶装置 ***)
{*} code : array[codeRange] of codeType ; { コード部格納エリア }
{*} store : array[dataRange] of dataType ; { データ部格納エリア }
(*** P-code仮想計算機レジスタ ***)
pc : codeRange ; { プログラムカウンタ }
mp : dataRange ; { スタック枠の始まりを保持する }
np : dataRange ; { ヒープ領域の末尾を保持する }
sp : dataRange1 ; { スタックポインタ }
ep : dataRange ; { スタック枠の最大を保持する }
inputAdr : dataRange ; { input ファイルバッファ変数アドレス }
outputAdr : dataRange ; { outputファイルバッファ変数アドレス }
(****************************)
(* 初期設定処理 *)
(****************************)
procedure initialize ;
var cc : codeRange ;
dc : dataRange ;
begin
(*** コードファイルの読み込み ***)
reset(pcode) ;
cc := 0 ;
while not eof(pcode) do
begin
read(pcode,code[cc]) ;
cc := cc + 1
end ;
(*** 定数ファイルの読み込み ***)
reset(pconst) ;
dc := 0 ;
while not eof(pConst) do
begin
read(pConst,store[dc]) ;
dc := dc + 1
end ;
(*** レジスタ類初期設定 ***)
pc := 0 ;
mp := dc ;
sp := mp - 1 ;
ep := mp ;
np := MaxData ;
(*** バッファ変数アドレス設定 ***)
inputAdr := mp + 5 ;
outputAdr := mp + 6
end {initialize} ;
(****************************)
(* ランタイムエラーメッセージ出力処理 *)
(****************************)
procedure RunErr(errorNum : integer) ;
begin
writeln ;
write('*** [ADDR=',pc-1:1,'] HAPPy Run-time error R',errorNum:1,
': 処理打ち切り ***') ;
goto 9999
end ;
(****************************)
(* 解釈実行処理 *)
(****************************)
procedure interpret ;
var run : Boolean ;
trace : Boolean ;
width : integer ;
ad : dataRange1 ;
leng : integer ;
i : integer ;
low,high : integer ;
s : setType ;
(**** 基準アドレス取得関数 ****)
function base(p : pType) : dataRange ;
var ad : dataRange ;
i : pType ;
begin
if p = 0 then base := mp
else begin
ad := mp ;
for i:=1 to p do ad := store[ad+1].va ; { 静鎖をたどる }
base := ad
end
end {base} ;
(***** 文字列比較関数 *****)
(* 関数値 : < 0 ・・・ 小さい 0 ・・・ 等しい >0 ・・・ 大きい *)
function cmpStr(length : integer) : integer ;
label 9 ;
var i : integer ;
diff : integer ;
begin
for i:=0 to length-1 do
begin
diff := ord(store[store[sp ].va+i].vc)
- ord(store[store[sp+1].va+i].vc) ;
if diff <> 0 then goto 9
end ;
9 :
cmpStr := diff
end {cmpStr} ;
begin {interpret}
run := true ;
trace := false ;
while run do { stp 命令を実行するまで }
with code[pc] do
begin
if trace then { トレースが必要な時 }
writeln(pc:4,':',ord(op):4,
' mp=',mp:4,' ep=',ep:4,' np=',np:4,
' store[',sp:4,']=',store[sp].vi) ;
{ ↑ sp=-1 の時は誤り 要検討 }
pc := pc + 1 ; { 命令をフェッチ後にプログラムカウンタを更新する }
case op of
iABI : (* absolute integers *)
store[sp].vi := abs(store[sp].vi) ;
iABR : (* absolute reals *)
store[sp].vr := abs(store[sp].vr) ;
iADI : begin (* add integers *)
sp := sp - 1 ;
store[sp].vi := store[sp].vi + store[sp+1].vi
end ;
iADR : begin (* add reals *)
sp := sp - 1 ;
store[sp].vr := store[sp].vr + store[sp+1].vr
end ;
iAND : begin (* and operator *)
sp := sp - 1 ;
store[sp].vb := store[sp].vb and store[sp+1].vb
end ;
iATN : (* arctan standard function *)
store[sp].vr := arctan(store[sp].vr) ;
iBAS : begin (* load base mark address *)
sp := sp + 1 ;
store[sp].va := base(p)
end ;
iCHK : (* check value between bounds *)
if (store[sp].vi < store[q ].vi) or
(store[sp].vi > store[q+1].vi) then RunErr(p) ;
iCHR : begin (* chr standard function *)
if (0 > store[sp].vi) or (255 < store[sp].vi) then
RunErr(37) ; { 引数値異常 }
store[sp].vc := chr(store[sp].vi)
end ;
iCKA : (* check address *)
if store[sp].va = NilValue then RunErr(3) { nil }
else if store[sp].va < np then RunErr(4) ; { 不定 }
iCKS : (* check set *)
if not (store[sp].vs <= store[q].vs) then RunErr(p) ;
iCOS : (* cos standard function *)
store[sp].vr := cos(store[sp].vr) ;
iCUI : begin (* call user procedure indirect *)
sp := sp - 1 ;
mp := sp - (p + 4) ;
store[mp+4].vp := pc ;
pc := store[sp+1].vp
end ;
iCUP : begin (* call user procedure *)
mp := sp - (p+4) ;
store[mp+4].vp := pc ;
pc := q
end ;
iDEC : (* decrement *)
case p of
DatAd : store[sp].va := store[sp].va - q ;
Inte : store[sp].vi := store[sp].vi - q ;
Bool : store[sp].vb := false ; { 偽以外になることはない }
Chars : store[sp].vc := chr(ord(store[sp].vc) - q)
end ;
iDIF : begin (* difference set *)
sp := sp - 1 ;
store[sp].vs := store[sp].vs - store[sp+1].vs
end ;
iDIS : begin (* dispose standard procedure *)
ad := store[sp].va ;
if ad = NilValue then RunErr(23) ; { 引数の値がnil }
if np <= ad then
begin
if ad = np then np := np + q { 最も最近にnewされた時のみ }
end
else RunErr(24) { 引数の値が不定 }
end ;
iDVI : begin (* divide integers *)
if store[sp].vi = 0 then RunErr(45) ; { div演算子 0除算 }
sp := sp - 1 ;
store[sp].vi := store[sp].vi div store[sp+1].vi
end ;
iDVR : begin (* divide reals *)
if store[sp].vr = 0.0 then RunErr(44); { / 演算子 0除算 }
sp := sp - 1 ;
store[sp].vr := store[sp].vr / store[sp+1].vr
end ;
iEJP : begin (* extra block jump *)
ad := base(p) ;
while mp <> ad do { スタックの枠を解放 }
begin
sp := mp - 1 ;
ep := store[mp+3].va ;
mp := store[mp+2].va { 動鎖 }
end ;
pc := q
end ;
iENT : begin (* enter procedure or function *)
if mp + p + q -1 > maxData then RunErr(122) ;
sp := mp + q - 1 ;
ep := sp + p ;
if ep >= np then RunErr(122) { スタック用メモリ不足 }
end ;
iEOF : begin (* eof standard function *)
sp := sp + 1 ;
if p = 0 then store[sp].vb := eof(input)
else store[sp].vb := eof(output) { 常に真 }
end ;
iEOL : begin (* eoln standard function *)
sp := sp + 1 ;
if p = 0 then store[sp].vb := eoln(input)
else RunErr(42) { outputは常にeofが真だから誤り }
{ 本物はバグのため誤りにならない}
end ;
iEQU : begin (* equal operator *)
sp := sp - 1 ;
case p of
DatAd : store[sp].vb := store[sp].va = store[sp+1].va ;
Inte : store[sp].vb := store[sp].vi = store[sp+1].vi ;
Reals : store[sp].vb := store[sp].vr = store[sp+1].vr ;
Bool : store[sp].vb := store[sp].vb = store[sp+1].vb ;
Sets : store[sp].vb := store[sp].vs = store[sp+1].vs ;
Multi : store[sp].vb := cmpStr(q) = 0 ;
Chars : store[sp].vb := store[sp].vc = store[sp+1].vc
end
end ;
iEXP : (* exp standard function *)
store[sp].vr := exp(store[sp].vr) ;
iFJP : begin (* jump on false *)
if not store[sp].vb then pc := q ;
sp := sp - 1
end ;
iFLO : (* float integer to real on sp-1 *)
store[sp-1].vr := store[sp-1].vi ;
iFLT : (* float integer to real *)
store[sp].vr := store[sp].vi ;
iGEQ : begin (* grater than equal operator *)
sp := sp - 1 ;
case p of
Inte : store[sp].vb := store[sp].vi >= store[sp+1].vi ;
Reals : store[sp].vb := store[sp].vr >= store[sp+1].vr ;
Bool : store[sp].vb := store[sp].vb >= store[sp+1].vb ;
Sets : store[sp].vb := store[sp].vs >= store[sp+1].vs ;
Multi : store[sp].vb := cmpStr(q) >= 0 ;
Chars : store[sp].vb := store[sp].vc >= store[sp+1].vc
end
end ;
iGET : ; (* get from not text *)
{ input,output以外のファイルはサポートしないので
この命令は出現しない }
iGRT : begin (* grater than operator *)
sp := sp - 1 ;
case p of
Inte : store[sp].vb := store[sp].vi > store[sp+1].vi ;
Reals : store[sp].vb := store[sp].vr > store[sp+1].vr ;
Bool : store[sp].vb := store[sp].vb > store[sp+1].vb ;
Multi : store[sp].vb := cmpStr(q) > 0 ;
Chars : store[sp].vb := store[sp].vc > store[sp+1].vc
end
end ;
iINC : (* increment *)
case p of
DatAd : store[sp].va := store[sp].va + q ;
Inte : store[sp].vi := store[sp].vi + q ;
Bool : store[sp].vb := true ; { 真以外はありえない }
Chars : store[sp].vc := chr(ord(store[sp].vc) + q)
end ;
iIND : (* indexed fetch *)
store[sp] := store[store[sp].va+q] ;
iINN : begin (* in operator *)
sp := sp - 1 ;
store[sp].vb := store[sp].vi in store[sp+1].vs
end ;
iINT : begin (* intersection set *)
sp := sp - 1 ;
store[sp].vs := store[sp].vs * store[sp+1].vs
end ;
iIOR : begin (* or operator *)
sp := sp - 1 ;
store[sp].vb := store[sp].vb or store[sp+1].vb
end ;
iIXA : begin (* indeced address *)
sp := sp - 1 ;
store[sp].va := store[sp].va +
store[q+1].vi * (store[sp+1].vi - store[q].vi)
end ;
iLAO , (* load base-level address *)
iLCA : begin (* load address of constant *)
sp := sp + 1 ;
store[sp].va := q
end ;
iLAP : begin (* load address of procedure *)
sp := sp + 1 ;
store[sp].vp := q
end ;
iLDA : begin (* load level p address *)
sp := sp + 1 ;
store[sp].va := base(p) + q
end ;
iLDC : begin (* load constant *)
sp := sp + 1 ;
case p of
Nils : store[sp].va := NilValue ; { nil値ロード }
Inte : store[sp].vi := q ;
Reals : store[sp].vr := store[q].vr ;
Bool : store[sp].vb := q = 1 ;
Sets : store[sp].vs := store[q].vs ;
Chars : store[sp].vc := chr(q)
end
end ;
iLDO : begin (* load contents of base-level address *)
sp := sp + 1 ;
if (p = Chars) and (q = inputAdr) then { input^に対する }
begin { ldoc命令 }
store[inputAdr].vc := input^ ;
store[sp ].vc := input^
end
else store[sp] := store[q]
{ それ以外のldo命令はデータタイプ関係なく丸ごとロード }
end ;
iLEQ : begin (* less than equal operator *)
sp := sp - 1 ;
case p of
Inte : store[sp].vb := store[sp].vi <= store[sp+1].vi ;
Reals : store[sp].vb := store[sp].vr <= store[sp+1].vr ;
Bool : store[sp].vb := store[sp].vb <= store[sp+1].vb ;
Sets : store[sp].vb := store[sp].vs <= store[sp+1].vs ;
Multi : store[sp].vb := cmpStr(q) <= 0 ;
Chars : store[sp].vb := store[sp].vc <= store[sp+1].vc
end
end ;
iLES : begin (* less than operator *)
sp := sp - 1 ;
case p of
Inte : store[sp].vb := store[sp].vi < store[sp+1].vi ;
Reals : store[sp].vb := store[sp].vr < store[sp+1].vr ;
Bool : store[sp].vb := store[sp].vb < store[sp+1].vb ;
Multi : store[sp].vb := cmpStr(q) < 0 ;
Chars : store[sp].vb := store[sp].vc < store[sp+1].vc
end
end ;
iLOD : begin (* load contents of address at level p *)
sp := sp + 1 ;
store[sp] := store[base(p)+q]
end ;
iLOG : begin (* ln standard function *)
if store[sp].vr <= 0.0 then RunErr(33) ; { 引数が0以下 }
store[sp].vr := ln(store[sp].vr)
end ;
iMMS : begin (* make multiple set *)
sp := sp - 1 ;
if p <= 1 then { p in [0,1] }
begin
low := store[sp ].vi ;
high := store[sp+1].vi
end
else { p in [2,3] }
begin
low := store[sp+1].vi ;
high := store[sp ].vi
end ;
if p in [1,3] then { -d デバッグオプションコンパイル }
if ( low <= high) and { 要素が作られる条件 }
((low < SetLow) or (high > SetHigh)) then
RunErr(112) ; { 集合要素順序数範囲外 }
s := [] ;
for i:=low to high do s := s + [i] ;
store[sp].vs := s
end ;
iMOD : begin (* modulo operator *)
if store[sp].vi <= 0 then RunErr(46) ; { 被演算子 <=0 }
sp := sp - 1 ;
store[sp].vi := store[sp].vi mod store[sp+1].vi
end ;
iMOV : begin (* move *)
if p = 1 then
for i:=0 to q-1 do
store[store[sp-1].va+i] := store[store[sp ].va+i]
else { p = 2 }
for i:=0 to q -1 do
store[store[sp ].va+i] := store[store[sp-1].va+i] ;
sp := sp - 2
end ;
iMPI : begin (* mulutiple integers *)
sp := sp - 1 ;
store[sp].vi := store[sp].vi * store[sp+1].vi
end ;
iMPR : begin (* mulutiple reals *)
sp := sp - 1 ;
store[sp].vr := store[sp].vr * store[sp+1].vr
end ;
iMSI : begin (* mark stack indirect *)
sp := sp - 1 ;
store[sp+2].va := store[sp+1].va ;
store[sp+3].va := mp ;
store[sp+4].va := ep ;
sp := sp + 5
end ;
iMST : begin (* mark stack *)
store[sp+2].va := base(p) ; { 静鎖 }
store[sp+3].va := mp ; { 動鎖 }
store[sp+4].va := ep ;
sp := sp + 5
end ;
iNEQ : begin (* not equal operator *)
sp := sp - 1 ;
case p of
Datad : store[sp].vb := store[sp].va <> store[sp+1].va ;
Inte : store[sp].vb := store[sp].vi <> store[sp+1].vi ;
Reals : store[sp].vb := store[sp].vr <> store[sp+1].vr ;
Bool : store[sp].vb := store[sp].vb <> store[sp+1].vb ;
Sets : store[sp].vb := store[sp].vs <> store[sp+1].vs ;
Multi : store[sp].vb := cmpStr(q) <> 0 ;
Chars : store[sp].vb := store[sp].vc <> store[sp+1].vc
end
end ;
iNEW : begin (* new standard procedure *)
np := np - q ; { q : 割当要求量 }
if np <= ep then RunErr(121) ; { メモリ不足で割り付け不能 }
store[store[sp].va].va := np ;
sp := sp - 1
end ;
iNGI : (* negative integers *)
store[sp].vi := -store[sp].vi ;
iNGR : (* negative reals *)
store[sp].vr := -store[sp].vr ;
iNOT : (* not operator *)
store[sp].vb := not store[sp].vb ;
iNXT : (* next to *)
case p of
Inte : store[mp+q].vi := succ(store[mp+q].vi) ;
Bool : store[mp+q].vb := succ(store[mp+q].vb) ;
Chars : store[mp+q].vc := succ(store[mp+q].vc)
end ;
iNXD : (* next downto *)
case p of
Inte : store[mp+q].vi := pred(store[mp+q].vi) ;
Bool : store[mp+q].vb := pred(store[mp+q].vb) ;
Chars : store[mp+q].vc := pred(store[mp+q].vc)
end ;
iODD : (* odd standard function *)
store[sp].vb := odd(store[sp].vi) ;
iORD : (* ord standard function *)
case p of
Chars : store[sp].vi := ord(store[sp].vc) ; { ordc }
Bool : store[sp].vi := ord(store[sp].vb) { ordb }
end ;
iPGE : (* page standard procedure *)
if p = 0 then RunErr(9) { inputは生成モードでない }
else page(output) ;
iPUT : ; (* put from not text *)
{ input,output以外のファイルはサポートしないので
この命令は出現しない }
iRDC : begin (* read character *)
if p = 1 then RunErr(14) ; { outputは検査モードでない }
read(input,store[store[sp].va].vc) ;
store[inputAdr].vc := input^ ;
sp := sp - 1
end ;
iRDI : begin (* read integer *)
if p = 1 then RunErr(14) ; { outputは検査モードでない }
read(input,store[store[sp].va].vi) ;
store[inputAdr].vc := input^ ;
sp := sp - 1
end ;
iRDR : begin (* read real *)
if p = 1 then RunErr(14) ; { outputは検査モードでない }
read(input,store[store[sp].va].vr) ;
store[inputAdr].vc := input^ ;
sp := sp - 1
end ;
iRET : begin (* return from procedure or function *)
if p = Proc then sp := mp - 1 { 手続きの戻り }
else sp := mp ; { 関数 の戻り }
pc := store[mp+4].vp ;
ep := store[mp+3].va ;
mp := store[mp+2].va
end ;
iRLN : (* readln standard procedure *)
if p = 1 then RunErr(14) { outputは検査モードでない }
else readln(input) ;
iROU : (* round standard function *)
store[sp].vi := round(store[sp].vr) ;
iRST : ; (* reset for not text *)
{ input,output以外のファイルはサポートしないので
この命令は出現しない }
iRWT : ; (* rewrite for not text *)
{ input,output以外のファイルはサポートしないので
この命令は出現しない }
iSBI : begin (* subtract integers *)
sp := sp - 1 ;
store[sp].vi := store[sp].vi - store[sp+1].vi
end ;
iSBR : begin (* subtract reals *)
sp := sp - 1 ;
store[sp].vr := store[sp].vr - store[sp+1].vr
end ;
iSGS : (* create singleton set *)
store[sp].vs := [store[sp].vi] ;
iSIN : (* sin standard function *)
store[sp].vr := sin(store[sp].vr) ;
iSQI : (* square integers *)
store[sp].vi := sqr(store[sp].vi) ;
iSQR : (* square reals *)
store[sp].vr := sqr(store[sp].vr) ;
iSQT : begin (* sqrt standard function *)
if store[sp].vr < 0.0 then RunErr(34) ; { 引数が負 }
store[sp].vr := sqrt(store[sp].vr)
end ;
iSRO : begin (* store at base-level address *)
store[q] := store[sp] ;
sp := sp - 1
end ;
iSTO : begin (* store indirect *)
store[store[sp-1].va] := store[sp] ;
sp := sp - 2
end ;
iSTP : (* stop *)
run := false ;
iSTR : begin (* store contents at address at level p *)
store[base(p)+q] := store[sp] ;
sp := sp - 1
end ;
iTGT : begin (* get from text *)
if p = 1 then RunErr(14) ; { outputは検査モードでない }
get(input) ;
store[inputAdr].vc := input^
end ;
iTPT : begin (* put from text *)
if p = 0 then RunErr(9) ; { inputは生成モードでない }
output^ := store[outputAdr].vc ;
put(output)
end ;
iTRA : (* trace of execution *)
trace := p = 1 ;
iTRC : (* trunc standard function *)
store[sp].vi := trunc(store[sp].vr) ;
iTRS : (* reset for text file *)
RunErr(81) ; { input,outputファイルに対してresetできない }
iTRW : (* rewrite for text file *)
RunErr(82) ; { input,outputファイルに対してrewriteできない }
iUJC : (* check uncondition jump *)
RunErr(51) ; { case文の選択式の値に合致する選択定数がない }
iUJP : (* uncondition jump *)
pc := q ;
iUNI : begin (* union set *)
sp := sp - 1 ;
store[sp].vs := store[sp].vs + store[sp+1].vs
end ;
iWLN : (* writeln standard procedure *)
if p = 0 then RunErr(9) { inputは生成モードでない }
else writeln(output) ;
iWRB : begin (* write boolean *)
if p = 0 then RunErr(9) ; { inputは生成モードでない } write(output,store[sp-1].vb:store[sp].vi) ;
sp := sp - 2
end ;
iWRC : begin (* write char *)
if p = 0 then RunErr(9) ; { inputは生成モードでない }
write(output,store[sp-1].vc:store[sp].vi) ;
sp := sp -2
end ;
iWRF : begin (* write real fix *)
if p = 0 then RunErr(9) ; { inputは生成モードでない }
write(output,store[sp-2].vr:store[sp-1].vi:store[sp].vi) ;
sp := sp - 3
end ;
iWRI : begin (* write integer *)
if p = 0 then RunErr(9) ; { inputは生成モードでない }
write(output,store[sp-1].vi:store[sp].vi) ;
sp := sp - 2
end ;
iWRR : begin (* write real *)
if p = 0 then RunErr(9) ; { inputは生成モードでない }
write(output,store[sp-1].vr:store[sp].vi) ;
sp := sp - 2
end ;
iWRS : begin (* write string *)
if p = 2 then RunErr(9) ; { inputは生成モードでない }
{ p = 2 は 正確にはoutput以外のファイルの意味 }
width := store[sp].vi ;
ad := store[sp-1].va ;
leng := q ;
if width > leng then write(output,' ':width-leng)
else leng := width ;
for i:=0 to leng-1 do write(output,store[ad+i].vc) ;
sp := sp - 2
end ;
iXJP : begin (* indexed jump *)
pc := pc + store[sp].vi ;
sp := sp - 1
end
end {case op}
end {with code[pc]}
end {interpret} ;
(****************************)
(* メイン処理 *)
(****************************)
begin
initialize ; { 初期設定 }
interpret ; { 解釈実行 }
9999:
end.